/*
    Spherical Grid Volume Approximation: An algorithm for approximating the 
    volume of a compound object by keeping track of its members' positions in space.
    Copyright (C) 2009, Rodrigo Castano, FuDePAN

    This file is part of Spherical Grid Volume Approximation.

    Spherical Grid Volume Approximation is free software: you can redistribute 
    it and/or modify it under the terms of the GNU General Public License as published 
    by the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Spherical Grid Volume Approximation is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "grillado_collision.h"






inline void GrilladoCollision::add_non_volumetric_element(const nonvolElementHandler &id) {
	const GridCoord coord_x = id.get_m();
	const GridCoord coord_y = id.get_n();
	const GridCoord coord_z = id.get_z();
	matriz[coord_x][coord_y][coord_z].non_vol_ids.push_back(id.get_CustomId());
}


nonvolElementHandler GrilladoCollision::add_element( const nonvolGridAtom &a) {
	nonvolElementHandler res = get_non_vol_element_handler(a.x, a.y, a.z, a.id);
	add_non_volumetric_element(res);
	return res;
}



GrilladoCollision::GrilladoCollision(size_t a, size_t b, size_t c, Length R, Length D) throw 
			(Grillado<SphereInfo>::radiusOrDistanceParamException, Grillado<SphereInfo>::sizeParamException, bad_alloc)
			: Grillado<SphereInfo>(a, b, c, R, D) {};



GrilladoCollision::~GrilladoCollision() {}


// Se agrega un elemento a la esfera correspondiente a las coordenadas ingresadas
// como argumento.
// Adds an element to the sphere determined by coordinates x, y, z.


void GrilladoCollision::add_volumetric_element(const volElementHandler &id)  {
	const GridCoord coord_x = id.get_m();
	const GridCoord coord_y = id.get_n();
	const GridCoord coord_z = id.get_z();
	if(matriz[coord_x][coord_y][coord_z].vol_ids.empty() ) {
		aumentar_vol_parcial(coord_x,coord_y,coord_z);
	}
	matriz[coord_x][coord_y][coord_z].vol_ids.push_back(id.get_CustomId());
}








void GrilladoCollision::get_customIDs_container(Coord a, Coord b, Coord c,CustomIdIterator &it) const  {
	
  GridCoord coord_x;
  GridCoord coord_y;
  GridCoord coord_z;
  calcular_coord(a, b, c, coord_x, coord_y, coord_z); 
  
	
  const GridCoord x_plus = modulo((static_cast<int>(coord_x) +1) , v);
	const GridCoord x_minus = modulo((static_cast<int>(coord_x) - 1) , v);
	const GridCoord y_minus = modulo((static_cast<int>(coord_y) - 1) , w);
	const GridCoord y_plus = modulo((static_cast<int>(coord_y) + 1) , w);
	const GridCoord z_plus = modulo((static_cast<int>(coord_z) + 1) , z);
	const GridCoord z_minus = modulo((static_cast<int>(coord_z) - 1) , z);
	SphereInfo *info[27];
	info[0] = &matriz[coord_x][coord_y][coord_z];
	info[1] = &matriz[coord_x][coord_y][z_plus];
	info[2] = &matriz[coord_x][coord_y][z_minus];
	info[3] = &matriz[x_plus][coord_y][coord_z];
	info[4] = &matriz[x_minus][coord_y][coord_z];
	info[5] = &matriz[coord_x][y_plus][coord_z];
	info[6] = &matriz[coord_x][y_minus][coord_z];
 
 
 
 // These aren't taken into account
 
 	info[7] = &matriz[x_minus][y_minus][z_plus];
 	info[8] = &matriz[x_minus][coord_y][z_plus];
 	info[9] = &matriz[x_minus][y_plus][z_plus];
 	info[10] = &matriz[coord_x][y_minus][z_plus];
 	info[11] = &matriz[coord_x][y_plus][z_plus];
 	info[12] = &matriz[x_plus][y_minus][z_plus];
 	info[13] = &matriz[x_plus][coord_y][z_plus];
 	info[14] = &matriz[x_plus][y_plus][z_plus];
 
 
 	info[15] = &matriz[x_minus][y_minus][z_minus];
 	info[16] = &matriz[x_minus][coord_y][z_minus];
 	info[17] = &matriz[x_minus][y_plus][z_minus];
 	info[18] = &matriz[coord_x][y_minus][z_minus];
 	info[19] = &matriz[coord_x][y_plus][z_minus];
 	info[20] = &matriz[x_plus][y_minus][z_minus];
 	info[21] = &matriz[x_plus][coord_y][z_minus];
 	info[22] = &matriz[x_plus][y_plus][z_minus];
 
 
 	info[23] = &matriz[x_minus][y_minus][coord_z];
 	info[24] = &matriz[x_minus][y_plus][coord_z];
 	info[25] = &matriz[x_plus][y_minus][coord_z];
 	info[26] = &matriz[x_plus][y_plus][coord_z];
 
 

 	for(int i = 0; i<27;++i) {
 		it.insert(it.end(),info[i]->non_vol_ids.begin(), info[i]->non_vol_ids.end());
 		it.insert(it.end(),info[i]->vol_ids.begin(), info[i]->vol_ids.end());
	}
  
   
}

template <>
inline unsigned int Grillado<SphereInfo>::show_quantity(SphereInfo &sphere_data) const {
  return sphere_data.count();
}

